use std::io::Write;
use futures_util::StreamExt;
use crate::commands::logger::log_system_event;
use log::{debug, error, info};
use serde::{Deserialize, Serialize};
use tauri::{Emitter, Manager};

// 添加下载进度结构体
#[derive(Debug, Serialize, Clone)]
pub struct DownloadProgress {
    pub downloaded: u64,
    pub total: u64,
    pub speed: f64,
}


#[derive(Debug, Serialize, Deserialize)]
pub struct ReleaseInfo {
    pub id: u64,
    pub tag_name: String,
    pub target_commitish: String,
    pub prerelease: bool,
    pub name: String,
    pub body: String,
    pub author: Author,
    pub created_at: String,
    pub assets: Vec<ReleaseAsset>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Author {
    pub id: u64,
    pub login: String,
    pub name: String,
    pub avatar_url: String,
    pub url: String,
    pub html_url: String,
    pub remark: String,
    pub followers_url: String,
    pub following_url: String,
    pub gists_url: String,
    pub starred_url: String,
    pub subscriptions_url: String,
    pub organizations_url: String,
    pub repos_url: String,
    pub events_url: String,
    pub received_events_url: String,
    #[serde(rename = "type")]
    pub user_type: String,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct ReleaseAsset {
    pub name: String,
    pub browser_download_url: String,
}
#[tauri::command]
pub async fn check_for_updates(
    app_handle: tauri::AppHandle,
) -> Result<Option<ReleaseInfo>, String> {
    info!("=== 开始检查更新 ===");
    let _ = log_system_event(
        "INFO".to_string(),
        "updater".to_string(),
        "开始检查更新".to_string(),
        None,
        app_handle.clone(),
    )
        .await;

    let client = reqwest::Client::new();
    let current_version = env!("CARGO_PKG_VERSION");

    info!("当前版本: {}", current_version);
    let _ = log_system_event(
        "INFO".to_string(),
        "updater".to_string(),
        format!("当前版本: {}", current_version),
        None,
        app_handle.clone(),
    )
        .await;

    let url = "https://gitee.com/api/v5/repos/valklyrs/rdmp_tools/releases/latest";
    info!("请求URL: {}", url);
    let _ = log_system_event(
        "INFO".to_string(),
        "updater".to_string(),
        format!("请求URL: {}", url),
        None,
        app_handle.clone(),
    )
        .await;

    match client.get(url).send().await {
        Ok(response) => {
            info!("HTTP状态码: {}", response.status());
            let _ = log_system_event(
                "INFO".to_string(),
                "updater".to_string(),
                format!("HTTP状态码: {}", response.status()),
                None,
                app_handle.clone(),
            )
                .await;

            if response.status().is_success() {
                match response.json::<ReleaseInfo>().await {
                    Ok(release_info) => {
                        let latest_version = release_info.tag_name.trim_start_matches('v');

                        info!("最新版本: {}", latest_version);
                        let _ = log_system_event(
                            "INFO".to_string(),
                            "updater".to_string(),
                            format!("最新版本: {}", latest_version),
                            None,
                            app_handle.clone(),
                        )
                            .await;

                        let is_newer =
                            is_newer_version(latest_version, current_version, &app_handle);
                        info!(
                            "版本比较结果: {} > {} = {}",
                            latest_version, current_version, is_newer
                        );
                        let _ = log_system_event(
                            "INFO".to_string(),
                            "updater".to_string(),
                            format!(
                                "版本比较结果: {} > {} = {}",
                                latest_version, current_version, is_newer
                            ),
                            None,
                            app_handle.clone(),
                        )
                            .await;

                        debug!("发行版信息: {:?}", release_info);

                        if is_newer {
                            info!("发现新版本，返回更新信息");
                            let _ = log_system_event(
                                "INFO".to_string(),
                                "updater".to_string(),
                                "发现新版本，返回更新信息".to_string(),
                                None,
                                app_handle.clone(),
                            )
                                .await;
                            Ok(Some(release_info))
                        } else {
                            info!("当前已是最新版本");
                            let _ = log_system_event(
                                "INFO".to_string(),
                                "updater".to_string(),
                                "当前已是最新版本".to_string(),
                                None,
                                app_handle.clone(),
                            )
                                .await;
                            Ok(None)
                        }
                    }
                    Err(e) => {
                        let error_msg = format!("解析发行版信息失败: {}", e);
                        error!("{}", error_msg);
                        let _ = log_system_event(
                            "ERROR".to_string(),
                            "updater".to_string(),
                            error_msg.clone(),
                            None,
                            app_handle.clone(),
                        )
                            .await;
                        Err(error_msg)
                    }
                }
            } else {
                let error_msg = format!("获取发行版信息失败: HTTP {}", response.status());
                error!("{}", error_msg);
                let _ = log_system_event(
                    "ERROR".to_string(),
                    "updater".to_string(),
                    error_msg.clone(),
                    None,
                    app_handle.clone(),
                )
                    .await;
                Err(error_msg)
            }
        }
        Err(e) => {
            let error_msg = format!("网络请求失败: {}", e);
            error!("{}", error_msg);
            let _ = log_system_event(
                "ERROR".to_string(),
                "updater".to_string(),
                error_msg.clone(),
                None,
                app_handle.clone(),
            )
                .await;
            Err(error_msg)
        }
    }
}
#[tauri::command]
pub async fn download_update(
    download_url: String,
    app_handle: tauri::AppHandle,
) -> Result<String, String> {
    info!("开始下载更新: {}", download_url);
    let _ = log_system_event(
        "INFO".to_string(),
        "updater".to_string(),
        format!("开始下载更新: {}", download_url),
        None,
        app_handle.clone(),
    )
        .await;

    let client = reqwest::Client::new();

    // 获取应用目录
    let app_dir = app_handle.path().app_data_dir().map_err(|e| {
        let error_msg = format!("无法获取应用目录: {}", e);
        error!("{}", error_msg);
        let _ = futures::executor::block_on(log_system_event(
            "ERROR".to_string(),
            "updater".to_string(),
            error_msg.clone(),
            None,
            app_handle.clone(),
        ));
        error_msg
    })?;

    info!("应用数据目录: {:?}", app_dir);
    let _ = log_system_event(
        "INFO".to_string(),
        "updater".to_string(),
        format!("应用数据目录: {:?}", app_dir),
        None,
        app_handle.clone(),
    )
        .await;

    // 创建更新目录
    let update_dir = app_dir.join("updates");
    std::fs::create_dir_all(&update_dir).map_err(|e| {
        let error_msg = format!("创建更新目录失败: {}", e);
        error!("{}", error_msg);
        let _ = futures::executor::block_on(log_system_event(
            "ERROR".to_string(),
            "updater".to_string(),
            error_msg.clone(),
            None,
            app_handle.clone(),
        ));
        error_msg
    })?;

    info!("更新目录: {:?}", update_dir);
    let _ = log_system_event(
        "INFO".to_string(),
        "updater".to_string(),
        format!("更新目录: {:?}", update_dir),
        None,
        app_handle.clone(),
    )
        .await;

    // 发送GET请求获取响应
    let response = client.get(&download_url).send().await.map_err(|e| {
        let error_msg = format!("下载请求失败: {}", e);
        error!("{}", error_msg);
        let _ = futures::executor::block_on(log_system_event(
            "ERROR".to_string(),
            "updater".to_string(),
            error_msg.clone(),
            None,
            app_handle.clone(),
        ));
        error_msg
    })?;

    if !response.status().is_success() {
        let error_msg = format!("下载失败: HTTP {}", response.status());
        error!("{}", error_msg);
        let _ = log_system_event(
            "ERROR".to_string(),
            "updater".to_string(),
            error_msg.clone(),
            None,
            app_handle.clone(),
        )
            .await;
        return Err(error_msg);
    }

    // 获取文件总大小
    let total_size = response.content_length().unwrap_or(0);
    info!("文件总大小: {} bytes", total_size);
    let _ = log_system_event(
        "INFO".to_string(),
        "updater".to_string(),
        format!("文件总大小: {} bytes", total_size),
        None,
        app_handle.clone(),
    )
        .await;

    let file_name = "rdmp-tools-new.exe";
    let file_path = update_dir.join(file_name);

    info!("下载文件保存路径: {:?}", file_path);
    let _ = log_system_event(
        "INFO".to_string(),
        "updater".to_string(),
        format!("下载文件保存路径: {:?}", file_path),
        None,
        app_handle.clone(),
    )
        .await;

    // 创建文件
    let mut file = std::fs::File::create(&file_path).map_err(|e| {
        let error_msg = format!("创建文件失败: {}", e);
        error!("{}", error_msg);
        let _ = futures::executor::block_on(log_system_event(
            "ERROR".to_string(),
            "updater".to_string(),
            error_msg.clone(),
            None,
            app_handle.clone(),
        ));
        error_msg
    })?;

    // 流式下载并发送进度事件
    let mut stream = response.bytes_stream();
    let mut downloaded: u64 = 0;
    let start_time = std::time::Instant::now();
    let mut last_progress_time = start_time;

    while let Some(chunk) = stream.next().await {
        let chunk = chunk.map_err(|e| {
            let error_msg = format!("下载数据块失败: {}", e);
            error!("{}", error_msg);
            let _ = futures::executor::block_on(log_system_event(
                "ERROR".to_string(),
                "updater".to_string(),
                error_msg.clone(),
                None,
                app_handle.clone(),
            ));
            error_msg
        })?;

        // 写入文件
        file.write_all(&chunk).map_err(|e| {
            let error_msg = format!("写入文件失败: {}", e);
            error!("{}", error_msg);
            let _ = futures::executor::block_on(log_system_event(
                "ERROR".to_string(),
                "updater".to_string(),
                error_msg.clone(),
                None,
                app_handle.clone(),
            ));
            error_msg
        })?;

        downloaded += chunk.len() as u64;

        // 每100ms发送一次进度更新，避免过于频繁
        let now = std::time::Instant::now();
        if now.duration_since(last_progress_time).as_millis() >= 100 {
            let elapsed = now.duration_since(start_time).as_secs_f64();
            let speed = if elapsed > 0.0 { downloaded as f64 / elapsed } else { 0.0 };

            let progress = DownloadProgress {
                downloaded,
                total: total_size,
                speed,
            };

            // 发送进度事件到前端
            if let Err(e) = app_handle.emit("download-progress", &progress) {
                error!("发送下载进度事件失败: {}", e);
            }

            last_progress_time = now;
        }
    }

    // 确保文件写入完成
    file.flush().map_err(|e| {
        let error_msg = format!("刷新文件缓冲区失败: {}", e);
        error!("{}", error_msg);
        let _ = futures::executor::block_on(log_system_event(
            "ERROR".to_string(),
            "updater".to_string(),
            error_msg.clone(),
            None,
            app_handle.clone(),
        ));
        error_msg
    })?;

    // 发送最终进度
    let final_progress = DownloadProgress {
        downloaded,
        total: total_size,
        speed: 0.0,
    };
    if let Err(e) = app_handle.emit("download-progress", &final_progress) {
        error!("发送最终下载进度事件失败: {}", e);
    }

    info!("下载完成，文件大小: {} bytes", downloaded);
    let _ = log_system_event(
        "INFO".to_string(),
        "updater".to_string(),
        format!("下载完成，文件大小: {} bytes", downloaded),
        None,
        app_handle.clone(),
    )
        .await;

    info!("文件保存成功: {:?}", file_path);
    let _ = log_system_event(
        "INFO".to_string(),
        "updater".to_string(),
        format!("文件保存成功: {:?}", file_path),
        None,
        app_handle.clone(),
    )
        .await;

    Ok(file_path.to_string_lossy().to_string())
}

#[tauri::command]
pub async fn apply_update(
    new_exe_path: String,
    app_handle: tauri::AppHandle,
) -> Result<(), String> {
    info!("开始应用更新: {}", new_exe_path);
    let _ = log_system_event(
        "INFO".to_string(),
        "updater".to_string(),
        format!("开始应用更新: {}", new_exe_path),
        None,
        app_handle.clone(),
    )
    .await;

    // 创建更新脚本
    let script_content = create_update_script(&new_exe_path, &app_handle)?;

    let app_dir = app_handle.path().app_data_dir().map_err(|e| {
        let error_msg = format!("无法获取应用目录: {}", e);
        error!("{}", error_msg);
        let _ = futures::executor::block_on(log_system_event(
            "ERROR".to_string(),
            "updater".to_string(),
            error_msg.clone(),
            None,
            app_handle.clone(),
        ));
        error_msg
    })?;

    let script_path = app_dir.join("update.bat");
    info!("更新脚本路径: {:?}", script_path);
    let _ = log_system_event(
        "INFO".to_string(),
        "updater".to_string(),
        format!("更新脚本路径: {:?}", script_path),
        None,
        app_handle.clone(),
    )
    .await;

    std::fs::write(&script_path, script_content).map_err(|e| {
        let error_msg = format!("创建更新脚本失败: {}", e);
        error!("{}", error_msg);
        let _ = futures::executor::block_on(log_system_event(
            "ERROR".to_string(),
            "updater".to_string(),
            error_msg.clone(),
            None,
            app_handle.clone(),
        ));
        error_msg
    })?;

    info!("更新脚本创建成功");
    let _ = log_system_event(
        "INFO".to_string(),
        "updater".to_string(),
        "更新脚本创建成功".to_string(),
        None,
        app_handle.clone(),
    )
    .await;

    // 执行更新脚本并退出应用
    #[cfg(target_os = "windows")]
    {
        info!("启动更新脚本...");
        let _ = log_system_event(
            "INFO".to_string(),
            "updater".to_string(),
            "启动更新脚本...".to_string(),
            None,
            app_handle.clone(),
        )
        .await;

        std::process::Command::new("cmd")
            .args(["/C", "start", "", script_path.to_str().unwrap()])
            .spawn()
            .map_err(|e| {
                let error_msg = format!("启动更新脚本失败: {}", e);
                error!("{}", error_msg);
                let _ = futures::executor::block_on(log_system_event(
                    "ERROR".to_string(),
                    "updater".to_string(),
                    error_msg.clone(),
                    None,
                    app_handle.clone(),
                ));
                error_msg
            })?;
    }

    // 延迟退出应用
    let app_handle_clone = app_handle.clone();
    std::thread::spawn(move || {
        info!("2秒后退出应用以完成更新");
        let _ = futures::executor::block_on(log_system_event(
            "INFO".to_string(),
            "updater".to_string(),
            "2秒后退出应用以完成更新".to_string(),
            None,
            app_handle_clone,
        ));
        std::thread::sleep(std::time::Duration::from_secs(2));
        std::process::exit(0);
    });

    Ok(())
}

fn create_update_script(
    new_exe_path: &str,
    app_handle: &tauri::AppHandle,
) -> Result<String, String> {
    info!("创建更新脚本，新文件路径: {}", new_exe_path);
    let _ = futures::executor::block_on(log_system_event(
        "INFO".to_string(),
        "updater".to_string(),
        format!("创建更新脚本，新文件路径: {}", new_exe_path),
        None,
        app_handle.clone(),
    ));

    let current_exe = std::env::current_exe().map_err(|e| {
        let error_msg = format!("获取当前执行文件路径失败: {}", e);
        error!("{}", error_msg);
        let _ = futures::executor::block_on(log_system_event(
            "ERROR".to_string(),
            "updater".to_string(),
            error_msg.clone(),
            None,
            app_handle.clone(),
        ));
        error_msg
    })?;

    info!("当前执行文件路径: {:?}", current_exe);
    let _ = futures::executor::block_on(log_system_event(
        "INFO".to_string(),
        "updater".to_string(),
        format!("当前执行文件路径: {:?}", current_exe),
        None,
        app_handle.clone(),
    ));

    // 使用简化的脚本，避免复杂的字符和路径问题
    let current_exe_str = current_exe.to_string_lossy().to_string();
    let backup_name = format!("{}.backup", current_exe_str);

    let script = format!(
        r#"@echo off
chcp 65001 >nul
echo Updating application...
timeout /t 3 /nobreak >nul

echo Waiting for application to close...
timeout /t 2 /nobreak >nul

echo Creating backup...
if exist "{backup}" del "{backup}"
if exist "{current}" (
    move "{current}" "{backup}"
    if errorlevel 1 (
        echo Backup failed, retrying...
        timeout /t 2 /nobreak >nul
        move "{current}" "{backup}"
    )
)

echo Copying new version...
copy "{new}" "{current}"
if errorlevel 1 (
    echo Copy failed, restoring backup...
    if exist "{backup}" move "{backup}" "{current}"
    echo Update failed!
    pause
    exit /b 1
)

echo Verifying new file...
if not exist "{current}" (
    echo New file missing, restoring backup...
    if exist "{backup}" move "{backup}" "{current}"
    echo Update failed!
    pause
    exit /b 1
)

echo Cleaning up...
if exist "{new}" del "{new}"
if exist "{backup}" del "{backup}"

echo Update completed, restarting application...
start "" "{current}"

echo Cleaning up script...
del "%~f0"
"#,
        current = current_exe_str,
        backup = backup_name,
        new = new_exe_path
    );

    debug!("更新脚本内容:\n{}", script);
    let _ = futures::executor::block_on(log_system_event(
        "DEBUG".to_string(),
        "updater".to_string(),
        format!("更新脚本内容:\n{}", script),
        None,
        app_handle.clone(),
    ));

    Ok(script)
}

fn is_newer_version(latest: &str, current: &str, app_handle: &tauri::AppHandle) -> bool {
    debug!("比较版本: {} vs {}", latest, current);
    let _ = futures::executor::block_on(log_system_event(
        "DEBUG".to_string(),
        "updater".to_string(),
        format!("比较版本: {} vs {}", latest, current),
        None,
        app_handle.clone(),
    ));

    let parse_version =
        |v: &str| -> Vec<u32> { v.split('.').filter_map(|s| s.parse().ok()).collect() };

    let latest_parts = parse_version(latest);
    let current_parts = parse_version(current);

    debug!("解析后的版本号: {:?} vs {:?}", latest_parts, current_parts);
    let _ = futures::executor::block_on(log_system_event(
        "DEBUG".to_string(),
        "updater".to_string(),
        format!("解析后的版本号: {:?} vs {:?}", latest_parts, current_parts),
        None,
        app_handle.clone(),
    ));

    for i in 0..std::cmp::max(latest_parts.len(), current_parts.len()) {
        let latest_part = latest_parts.get(i).unwrap_or(&0);
        let current_part = current_parts.get(i).unwrap_or(&0);

        debug!("比较部分 {}: {} vs {}", i, latest_part, current_part);
        let _ = futures::executor::block_on(log_system_event(
            "DEBUG".to_string(),
            "updater".to_string(),
            format!("比较部分 {}: {} vs {}", i, latest_part, current_part),
            None,
            app_handle.clone(),
        ));

        if latest_part > current_part {
            debug!("发现新版本");
            let _ = futures::executor::block_on(log_system_event(
                "DEBUG".to_string(),
                "updater".to_string(),
                "发现新版本".to_string(),
                None,
                app_handle.clone(),
            ));
            return true;
        } else if latest_part < current_part {
            debug!("当前版本更新");
            let _ = futures::executor::block_on(log_system_event(
                "DEBUG".to_string(),
                "updater".to_string(),
                "当前版本更新".to_string(),
                None,
                app_handle.clone(),
            ));
            return false;
        }
    }

    debug!("版本相同");
    let _ = futures::executor::block_on(log_system_event(
        "DEBUG".to_string(),
        "updater".to_string(),
        "版本相同".to_string(),
        None,
        app_handle.clone(),
    ));
    false
}
